home *** CD-ROM | disk | FTP | other *** search
/ Isometric Game Programming with DirectX 7.0 / Isometric Game Programming.iso / source / chapter22 / isohex22_1 / isohex22_1.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-11-22  |  10.1 KB  |  425 lines

  1. /*****************************************************************************
  2. IsoHex22_1.cpp
  3. Ernest S. Pazera
  4. 22NOV2000
  5. Start a WIN32 Application Workspace, add in this file
  6. Requires GDICanvas.h/cpp
  7. No other libs are required
  8. *****************************************************************************/
  9.  
  10. //////////////////////////////////////////////////////////////////////////////
  11. //INCLUDES
  12. //////////////////////////////////////////////////////////////////////////////
  13. #define WIN32_LEAN_AND_MEAN  
  14.  
  15. #include <windows.h>   
  16. #include <stdlib.h>
  17. #include "gdicanvas.h"
  18.  
  19. //////////////////////////////////////////////////////////////////////////////
  20. //DEFINES
  21. //////////////////////////////////////////////////////////////////////////////
  22. //name for our window class
  23. #define WINDOWCLASS "ISOHEX22"
  24. //title of the application
  25. #define WINDOWTITLE "IsoHex 22-1"
  26.  
  27. //maze constants
  28. //size
  29. const int MAZE_WIDTH=16;
  30. const int MAZE_HEIGHT=16;
  31.  
  32. //directions
  33. const int MAZE_NORTH=0;
  34. const int MAZE_EAST=1;
  35. const int MAZE_SOUTH=2;
  36. const int MAZE_WEST=3;
  37. const int MAZE_DOORCOUNT=4;
  38.  
  39. //room structure
  40. struct Room
  41. {
  42.     //one door for each direction
  43.     bool Door[MAZE_DOORCOUNT];
  44. };
  45.  
  46. //////////////////////////////////////////////////////////////////////////////
  47. //PROTOTYPES
  48. //////////////////////////////////////////////////////////////////////////////
  49. bool Prog_Init();//game data initalizer
  50. void Prog_Loop();//main game loop
  51. void Prog_Done();//game clean up
  52. void MakeMaze();//make the maze
  53. int CountDoors(Room* pRoom);//count the doors in a room
  54. void DrawMaze();//draw the maze
  55.  
  56. //////////////////////////////////////////////////////////////////////////////
  57. //GLOBALS
  58. //////////////////////////////////////////////////////////////////////////////
  59. HINSTANCE hInstMain=NULL;//main application handle
  60. HWND hWndMain=NULL;//handle to our main window
  61.  
  62. //the maze
  63. Room Maze[MAZE_WIDTH][MAZE_HEIGHT];
  64.  
  65. //tileset for showing the maze(not a real tileset)
  66. CGDICanvas gdicMaze;
  67.  
  68. //////////////////////////////////////////////////////////////////////////////
  69. //WINDOWPROC
  70. //////////////////////////////////////////////////////////////////////////////
  71. LRESULT CALLBACK TheWindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
  72. {
  73.     //which message did we get?
  74.     switch(uMsg)
  75.     {
  76.     case WM_DESTROY://the window is being destroyed
  77.         {
  78.  
  79.             //tell the application we are quitting
  80.             PostQuitMessage(0);
  81.  
  82.             //handled message, so return 0
  83.             return(0);
  84.  
  85.         }break;
  86.     case WM_PAINT://the window needs repainting
  87.         {
  88.             //a variable needed for painting information
  89.             PAINTSTRUCT ps;
  90.             
  91.             //start painting
  92.             HDC hdc=BeginPaint(hwnd,&ps);
  93.  
  94.             //end painting
  95.             EndPaint(hwnd,&ps);
  96.  
  97.             //draw the maze
  98.             DrawMaze();
  99.                         
  100.             //handled message, so return 0
  101.             return(0);
  102.         }break;
  103.     }
  104.  
  105.     //pass along any other message to default message handler
  106.     return(DefWindowProc(hwnd,uMsg,wParam,lParam));
  107. }
  108.  
  109.  
  110. //////////////////////////////////////////////////////////////////////////////
  111. //WINMAIN
  112. //////////////////////////////////////////////////////////////////////////////
  113. int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
  114. {
  115.     //assign instance to global variable
  116.     hInstMain=hInstance;
  117.  
  118.     //create window class
  119.     WNDCLASSEX wcx;
  120.  
  121.     //set the size of the structure
  122.     wcx.cbSize=sizeof(WNDCLASSEX);
  123.  
  124.     //class style
  125.     wcx.style=CS_OWNDC | CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
  126.  
  127.     //window procedure
  128.     wcx.lpfnWndProc=TheWindowProc;
  129.  
  130.     //class extra
  131.     wcx.cbClsExtra=0;
  132.  
  133.     //window extra
  134.     wcx.cbWndExtra=0;
  135.  
  136.     //application handle
  137.     wcx.hInstance=hInstMain;
  138.  
  139.     //icon
  140.     wcx.hIcon=LoadIcon(NULL,IDI_APPLICATION);
  141.  
  142.     //cursor
  143.     wcx.hCursor=LoadCursor(NULL,IDC_ARROW);
  144.  
  145.     //background color
  146.     wcx.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
  147.  
  148.     //menu
  149.     wcx.lpszMenuName=NULL;
  150.  
  151.     //class name
  152.     wcx.lpszClassName=WINDOWCLASS;
  153.  
  154.     //small icon
  155.     wcx.hIconSm=NULL;
  156.  
  157.     //register the window class, return 0 if not successful
  158.     if(!RegisterClassEx(&wcx)) return(0);
  159.  
  160.     //create main window
  161.     hWndMain=CreateWindowEx(0,WINDOWCLASS,WINDOWTITLE, WS_BORDER | WS_SYSMENU | WS_CAPTION| WS_VISIBLE,0,0,320,240,NULL,NULL,hInstMain,NULL);
  162.  
  163.     //error check
  164.     if(!hWndMain) return(0);
  165.  
  166.     //if program initialization failed, then return with 0
  167.     if(!Prog_Init()) return(0);
  168.  
  169.     //message structure
  170.     MSG msg;
  171.  
  172.     //message pump
  173.     for(;;)    
  174.     {
  175.         //look for a message
  176.         if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
  177.         {
  178.             //there is a message
  179.  
  180.             //check that we arent quitting
  181.             if(msg.message==WM_QUIT) break;
  182.             
  183.             //translate message
  184.             TranslateMessage(&msg);
  185.  
  186.             //dispatch message
  187.             DispatchMessage(&msg);
  188.         }
  189.  
  190.         //run main game loop
  191.         Prog_Loop();
  192.     }
  193.     
  194.     //clean up program data
  195.     Prog_Done();
  196.  
  197.     //return the wparam from the WM_QUIT message
  198.     return(msg.wParam);
  199. }
  200.  
  201. //////////////////////////////////////////////////////////////////////////////
  202. //INITIALIZATION
  203. //////////////////////////////////////////////////////////////////////////////
  204. bool Prog_Init()
  205. {
  206.     //set the client area size
  207.     RECT rcTemp;
  208.     SetRect(&rcTemp,0,0,256,256);//256x256 client area
  209.     AdjustWindowRect(&rcTemp,WS_BORDER | WS_SYSMENU | WS_CAPTION| WS_VISIBLE,FALSE);//adjust the window size based on desired client area
  210.     SetWindowPos(hWndMain,NULL,0,0,rcTemp.right-rcTemp.left,rcTemp.bottom-rcTemp.top,SWP_NOMOVE);//set the window width and height
  211.  
  212.     //load in the maze image
  213.     gdicMaze.Load(NULL,"mazets.bmp");
  214.  
  215.     //make the maze
  216.     MakeMaze();
  217.  
  218.     return(true);//return success
  219. }
  220.  
  221. //////////////////////////////////////////////////////////////////////////////
  222. //CLEANUP
  223. //////////////////////////////////////////////////////////////////////////////
  224. void Prog_Done()
  225. {
  226.     //////////////////////////
  227.     //clean up code goes here
  228.     //////////////////////////
  229. }
  230.  
  231. //////////////////////////////////////////////////////////////////////////////
  232. //MAIN GAME LOOP
  233. //////////////////////////////////////////////////////////////////////////////
  234. void Prog_Loop()
  235. {
  236.     ///////////////////////////
  237.     //main game logic goes here
  238.     ///////////////////////////
  239. }
  240.  
  241. void MakeMaze()
  242. {
  243.     //start making the maze
  244.     //assumes the maze array is clean (i.e. all values are false)
  245.     int doorcount=0;//number of doors we have place
  246.     //x and y position of the room
  247.     int x;
  248.     int y;
  249.     int dir;//direction
  250.     //randomize the seed
  251.     srand(GetTickCount());
  252.     //clear out the maze
  253.     for(x=0;x<MAZE_WIDTH;x++)
  254.         for(y=0;y<MAZE_HEIGHT;y++)
  255.             for(dir=0;dir<MAZE_DOORCOUNT;dir++)
  256.                 Maze[x][y].Door[dir]=false;
  257.     while (doorcount<MAZE_WIDTH*MAZE_HEIGHT-1)
  258.     {
  259.         DrawMaze();
  260.         //this flag is set if a suitable room is found
  261.         bool found=false;
  262.         //blocks, used a little later
  263.         int blockcount;
  264.         bool block[MAZE_DOORCOUNT];
  265.         while(!found)
  266.         {
  267.             //if doorcount is 0, just pick a room
  268.             if(doorcount==0)
  269.             {
  270.                 x=rand()%MAZE_WIDTH;
  271.                 y=rand()%MAZE_HEIGHT;
  272.             }
  273.             else
  274.             {
  275.                 //doorcount not zero, pick a room with a door in it
  276.                 do
  277.                 {
  278.                     x=rand()%MAZE_WIDTH;
  279.                     y=rand()%MAZE_HEIGHT;
  280.                 } while (CountDoors(&Maze[x][y])==0);
  281.                 //CountDoors is pseudocode for a function we'll write later
  282.             }
  283.             //so far, so good, we have a room
  284.             //we now must analyze blocked passages
  285.             blockcount=0;
  286.             //loop through directions
  287.             for(dir=0;dir<MAZE_DOORCOUNT;dir++)
  288.             {
  289.                 //set block to false
  290.                 block[dir]=false;
  291.                 //if the door in the room for dir is set, set the block
  292.                 if(Maze[x][y].Door[dir])
  293.                 {
  294.                     block[dir]=true;
  295.                     blockcount++;
  296.                     continue;
  297.                 }
  298.                 //calculate the next position based on this direction
  299.                 int nx=x,ny=y;//next position
  300.                 switch(dir)
  301.                 {
  302.                 case MAZE_NORTH:
  303.                     {
  304.                         ny--;
  305.                     }break;
  306.                 case MAZE_EAST:
  307.                     {
  308.                         nx++;
  309.                     }break;
  310.                 case MAZE_SOUTH:
  311.                     {
  312.                         ny++;
  313.                     }break;
  314.                 case MAZE_WEST:
  315.                     {
  316.                         nx--;
  317.                     }break;
  318.                 }
  319.                 //bounds checking
  320.                 if(nx<0 || ny<0 || nx>=MAZE_WIDTH || ny>=MAZE_HEIGHT)
  321.                 {
  322.                     block[dir]=true;
  323.                     blockcount++;
  324.                     continue;
  325.                 }
  326.                 //final check, make sure the room at nx,ny has no doors
  327.                 if(CountDoors(&Maze[nx][ny])!=0)
  328.                 {
  329.                     block[dir]=true;
  330.                     blockcount++;
  331.                     continue;
  332.                 }
  333.             }
  334.             //if blockcount is not the same as MAZE_DOORCOUNT, we can place a door
  335.             if(blockcount!=MAZE_DOORCOUNT) found=true;
  336.         }
  337.         //found is now true, so we can place a door
  338.         do
  339.         {
  340.             //select a door direction
  341.             dir=rand()%MAZE_DOORCOUNT;
  342.         }while    (block[dir]);//make sure that direction is not blocked
  343.         //dir contains a valid direction
  344.         Maze[x][y].Door[dir]=true;
  345.         //move to next room
  346.         switch(dir)
  347.         {
  348.         case MAZE_NORTH:
  349.             {
  350.                 y--;
  351.             }break;
  352.         case MAZE_EAST:
  353.             {
  354.                 x++;
  355.             }break;
  356.         case MAZE_SOUTH:
  357.             {
  358.                 y++;
  359.             }break;
  360.         case MAZE_WEST:
  361.             {
  362.                 x--;
  363.             }break;
  364.         }
  365.         //change direction to opposite direction
  366.         dir=(dir+(MAZE_DOORCOUNT/2)) % MAZE_DOORCOUNT;
  367.         //set door in the next room
  368.         Maze[x][y].Door[dir]=true;
  369.         //increment the doorcount
  370.         doorcount++;
  371.     }
  372. }
  373.  
  374. int CountDoors(Room* pRoom)//count the doors in a room
  375. {
  376.     //initialize total to 0
  377.     int total=0;
  378.     //start counting doors
  379.     for(int dir=0;dir<MAZE_DOORCOUNT;dir++)
  380.     {
  381.         //if door is fount, add one to the total
  382.         if(pRoom->Door[dir]) total++;
  383.     }
  384.     //return total
  385.     return(total);
  386. }
  387.  
  388. void DrawMaze()
  389. {
  390.     //grab dc from window
  391.     HDC hdc=GetDC(hWndMain);
  392.     //loop variables
  393.     int x;
  394.     int y;
  395.     //image stuff
  396.     int imagex;
  397.     int imagey;
  398.     int imagenum;
  399.     //loop through columns
  400.     for(x=0;x<MAZE_WIDTH;x++)
  401.     {
  402.         //loop through rows
  403.         for(y=0;y<MAZE_HEIGHT;y++)
  404.         {
  405.             //put together the image number
  406.             imagenum=0;//initialize to 0
  407.             //north, add 1
  408.             if(Maze[x][y].Door[MAZE_NORTH]) imagenum+=1;
  409.             //east, add 2
  410.             if(Maze[x][y].Door[MAZE_EAST]) imagenum+=2;
  411.             //south, add 4
  412.             if(Maze[x][y].Door[MAZE_SOUTH]) imagenum+=4;
  413.             //west, add 8
  414.             if(Maze[x][y].Door[MAZE_WEST]) imagenum+=8;
  415.             //calculate the imagex and imagey
  416.             imagex=(imagenum%8)*16;
  417.             imagey=(imagenum/8)*16;
  418.             //blit the appropriate image
  419.             BitBlt(hdc,x*16,y*16,16,16,gdicMaze,imagex,imagey,SRCCOPY);
  420.         }
  421.     }
  422.     //release the dc
  423.     ReleaseDC(hWndMain,hdc);
  424. }
  425.